package com.jeeplus.cms.support;

import com.google.common.base.Splitter;
import com.jeeplus.cms.support.comparator.TreeNodeComparator;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.core.persistence.TreeEntity;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Sawyer
 * @date 2020-11-25
 */
public class TreeBuilder {

    private static final TreeNodeComparator TREE_NODE_COMPARATOR = new TreeNodeComparator();

    private static final Splitter TREE_ID_SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings();

    public static <T extends TreeEntity<T>> List<T> buildTree(List<T> sourceList, String excludeIds, String includeIds) {
        Map<String, String> excludeIdMap = TREE_ID_SPLITTER.splitToList(StringUtils.trimToEmpty(excludeIds))
                .stream().collect(Collectors.toMap(key -> key, value -> value, (v1, v2) -> v2));
        Map<String, String> includeIdMap = TREE_ID_SPLITTER.splitToList(StringUtils.trimToEmpty(includeIds))
                .stream().collect(Collectors.toMap(key -> key, value -> value, (v1, v2) -> v2));

        // 对原数据进行分组
        Map<String, List<T>> groupMap = sourceList.stream().collect(Collectors.groupingBy(T::getParentId));

        // 获取节点
        List<T> rootNodeList = groupMap.get("0");
        if (null == rootNodeList || rootNodeList.isEmpty()) {
            return Collections.emptyList();
        }

        // 遍历节点，获取每一个节点下面的子节点
        findChildren(groupMap, rootNodeList, excludeIdMap, includeIdMap);
        return rootNodeList;
    }

    @SuppressWarnings("unchecked")
    public static <T extends TreeEntity<T>> void findChildren(Map<String, List<T>> groupMap, List<T> nodeList,
                                                              Map<String, String> excludeIdMap, Map<String, String> includeIdMap) {
        // 排序
        nodeList.sort(TREE_NODE_COMPARATOR);
        Iterator<T> iterator = nodeList.iterator();
        while (iterator.hasNext()) {
            T node = iterator.next();
            boolean needExclude = excludeIdMap.containsKey(node.getId()) || (includeIdMap.size() > 0 && !includeIdMap.containsKey(node.getId()));
            // 排除
            if (needExclude) {
                iterator.remove();
                continue;
            }

            List<T> children = groupMap.get(node.getId());
            if (null != children && !children.isEmpty()) {
                node.setChildren(children);
                findChildren(groupMap, children, excludeIdMap, includeIdMap);
            }
        }
    }
}
